#ifndef APPLICATION_H
#define APPLICATION_H


#include "ListOfFunctions.h"
#include "ErkangStruct.h"
#include "Instance.h"

#include <vector>
#include <map>
#include <string>


namespace ErkangShuttle
{
	struct InstanceStructApplication
	{
		Instance* _pInstance{ nullptr };
		InstanceStruct _InstanceStruct;
	};
	class Application
	{
	public:
		// Singleton Application
		static Application& getApplicationInstance();


		~Application();
		void init();
		void setApplicationInfo(const char*, uint32_t, const char*, uint32_t);
		Instance& createInstance(const std::string&, const std::vector<const char*>& = std::vector<const char*>());
		Instance& getInstance(const std::string&);
		Instance& operator[](const std::string&);
		void destroyInstance(const std::string&);
		std::vector<const char*>& getAllInstanceExtensions();
		void setDefaultInstanceExtensions(std::vector<const char*>&);
	private:
		// Singleton Application
		Application() = default;
		Application(const Application&) = delete;
		Application(Application&&) = delete;
		Application& operator=(const Application&) = delete;
		static Application& m_Application;


		bool IsLibraryLoaded();
		bool LoadDynamicLibrary();
		bool FreeDynamicLibrary();
		bool LoadExportedFunctions();
		bool LoadGlobalFunctions();
		bool GetAllInstanceExtensions();
		bool IsInstanceExtensionsAvailable(std::vector<const char*>&);
		ListOfInstanceFunctions* LoadInstanceFunctions(VkInstance*);
		
		LIBRARY_TYPE m_VulkanLibrary{ nullptr };
		ListOfGlobalFunctions m_ListOfGlobalFunctions;
		VkApplicationInfo m_VkApplicationInfo{};

		std::map<std::string, InstanceStructApplication*> m_InstanceStructApplication;

		std::vector<VkExtensionProperties> m_AllAvailableVkInstanceExtensions;
		std::vector<const char*> m_AllAvailableVkInstanceExtensionNames;
		std::vector<const char*> m_DefaultInstanceExtensionNames;
	};
}

#endif // APPLICATION_H
